﻿'''
Author: Lucia Eder
Date: 16.04.2012

Programm zur Simulation des Sahelsyndroms
'''

from LEder_0080_Sahel import Sahel
import random
import csv
import psycopg2
from math import floor


class People(Sahel):
    '''
    Die Bevoelkerungsentwicklung ist vom Nahrungsangebot abhaengig, da es das 
    Bevoelkerungswachstum bestimmt. 
    '''
    def growth(self):
        return nutrition[len(nutrition) - 1] * self.growthrate * self.timestep


class Yield(Sahel):
    '''
    Der Ertrag ist positiv abhaengig von der Landnutzungsintensitaet und der 
    Produktivitaet und wird durch Konsum von Nahrung verringert.
    '''
    def growth(self):
        return landuse[len(landuse) - 1] * (
                productivity[len(productivity) - 1] * self.growthrate) * (
                self.timestep)
    def decrease(self):
        return nutrition[len(nutrition) - 1] * self.decreaserate * (
                self.timestep)
        
        
class Soil(Sahel):
    '''
    Die Fruchtbarkeit des Bodens wird von der Nutzungsintensitaet durch 
    Ertrag und Bevoelkerung negativ beeinflusst. 
    '''
    def growth(self):
        return (1 - self.stock[len(self.stock) - 1] / self.capacity) * (
                self.stock[len(self.stock) - 1]) * (
                wetness[len(wetness) - 1] * 100 * self.growthrate) * (
                self.timestep)
    def decrease(self):
        return landuse[len(landuse) - 1] * self.decreaserate * self.timestep


## Implementierung der Instanzen fuer alle drei Stocks und eine Instanz, die 
## die Rahmenbedingungen festlegt
env = Sahel("Umweltvariablen", 0, 0, 0, "differing units", 0, 0,
            120, 300, 1900, 2010, 0.01, 9, 4)
my_People = People("Bevoelkerung", 150, 0.3, 0.2, "Menschen", 0, 0.15, 
                   0, 0, 1900, 2010, 0.01)
my_Yield = Yield("Ertrag", 200, 0.01, 0.8, "Tonnen", 40, 0.1, 
                 0, 0, 1900, 2010, 0.01)
my_Soil = Soil("Bodenqualitaet", 60, 0.1, 0.02, "Tonnen pro Jahr", 100, 1.2,
               0, 0, 1900, 2010, 0.01)

## Jeder Instanz werden - soweit vorhanden - seine Konsumenten und Konsumierten 
## zugewiesen.
my_People.setPrey(my_Yield)
my_Yield.setPred(my_People)
my_Yield.setPrey(my_Soil)
my_Soil.setPred(my_Yield)

## Funktion zur Generierung einer raeumlich differenzierten Bodenqualitaet 
## an einer festgelegten Anzahl Plots
sq = [0.8 * (random.randint(60, 82)) for n in range(env.plots)]

## Daten zu Niederschlagsanomalien in der Sahelzone in Zeitraum von 1900 bis
## 2010 liegen in einer Datenbank vor.
con = psycopg2.connect ("host = localhost "
                        "dbname = PrecipitationSahel user = postgres")
cur = con.cursor()

for j in range (env.plots):

    ## Listen fuer die Zwischengroessen des Modells
    nutrition = [0]
    landuse = [0]
    productivity = [0]
    wetness = [0]
    
    ## Setzt nach jedem zeitlichen Durchlauf in einer Rasterzelle die Werte 
    ## auf die Anfangswerte, um dann die naechste Zelle ab t = 0 berechnen zu 
    ## koennen.
    my_Soil.setInitial()
    my_Yield.setInitial()
    my_People.setInitial()
    env.setInitial()
    
    ## Jedem Plot wird zu Beginn fuer den Beginn des Simulationszeitraums eine
    ## spezifische Bodenqualitaet zugewiesen.  
    my_Soil.stock[0]  = sq[j]   

    for time in range (int (env.timerange / env.timestep)):  

        ## Die Werte der Niederschlagsanomalien (nach NOAA in Janowiak, 1988 -
        ## http://jisao.washington.edu/data_sets/sahel/) werden aus einer
        ## lokalen Datenbank eingelesen und in dem Modellzeitraum
        ## fuer Berechnungen verwendet, in denen sie den erhobenen Jahres-
        ## zahlen der Datenbankwerten entsprechen. Es wird jeweils die Nieder-
        ## schlagsanomalie zum langjaehrigen Jahressummenmittel verwendet.
        cur.execute("SELECT precip FROM precipitation WHERE "
                    "year >= %s AND year < %s;",
                    (floor(env.initialtime[len(env.initialtime) - 1]),
                     floor(env.initialtime[len(env.initialtime) - 1] + 1)))
        precipit = cur.fetchone()
        
        ## Berechnung der Zwischengroessen des Modells
        nutrition.append(my_Yield.stock[len(my_Yield.stock) - 1] * (
                         my_People.stock[len(my_People.stock) - 1]) * (
                         my_People.influence))
        landuse.append(my_Soil.stock[len(my_Soil.stock) - 1] * (
                       my_Yield.stock[len(my_Yield.stock) - 1]) * (
                       my_People.stock[len(my_People.stock) - 1]) * (
                       my_Yield.influence))
        productivity.append(my_Soil.stock[len(my_Soil.stock) - 1] * (
                            my_Soil.influence / my_Yield.capacity))
        
        ## Berechnung des Feuchteangebotsfaktors, der aus einer 
        ## normalverteilten Zufallsfunktion und den Niederschlagsanomalien der 
        ## Sahelzone
        wetness.append(env.maxPrecip / (env.maxPrecip - env.minPrecip) - (
                       env.maxPrecip - random.gauss(200, 100) - (
                       10 * precipit[0])) / (
                       env.maxPrecip - env.minPrecip))

        my_Soil.setStock()
        my_Yield.setStock()
        my_People.setStock()
        env.setStock()
        
    my_Yield.getAllStocks(j)
    
    ## Fuer jeden Plot wird eine cvs-Datei mit der zeitlichen 
    ## Entwicklung des entsprehenden Stocks erstellt.
    soilfile = "soil_%s.csv" % j
    yieldfile = "yield_%s.csv" % j
    peoplefile = "people_%s.csv" % j
    soilwriter = csv.writer(open(soilfile, "wb"))
    soilwriter.writerow(my_Soil.stock)
    yieldwriter = csv.writer(open (yieldfile, "wb"))
    yieldwriter.writerow(my_Yield.stock)
    peoplewriter = csv.writer(open (peoplefile, "wb"))
    peoplewriter.writerow(my_People.stock)
    
    if j == env.visualPlot - 1:
        my_Yield.plotStock(env)

cur.close()
con.close()